<!--用于声明以下是一个HTML文档-->
<!DOCTYPE html>
<!--suppress ALL -->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>对象创建模式</title>
  </head>
  <body>
    <input value="1213123" />

    <!--对象创建模式-->
    <script>
      /**
       * 1.Object构造函数模式
       *   套路：先创建空Object对象，再动态添加属性/方法
       *   适用场景：起始时不确定对象内部数据
       *   缺点：语句太多
       * */
      var p1 = new Object();
      p1.name = "Tom";
      p1.age = 12;
      p1.setName = function (name) {
        this.name = name;
      };
      //测试
      p1.setName("Jack");
      console.log(p1.name, p1.age);

      /**
       * 2.对象字面量模式
       *   套路：使用{}创建对象，同时指定属性/方法
       *   适用场景：起始时对象内部数据是确定的
       *   缺点：如果创建多个对象，代码很重复
       * */
      var p2 = {
        name: "Tom2",
        age: 12,
        setName: function (name) {
          this.name = name;
        },
      };
      //测试
      console.log(p2.name, p2.age);
      p2.setName("Jack2");
      console.log(p2.name, p2.age);

      /**
       * 3.工厂模式：
       *   套路：通过工厂函数动态创建对象并返回
       *   适用场景: 需要创建多个对象
       *   缺点：对象没有一个具体的类型，都是Object类型
       * */
      function createPerson(name, age) {
        //返回一个对象的函数 ===> 工厂函数
        var obj = {
          name, //name:name   ES6写法
          age,
          setName: function (name) {
            this.name = name;
          },
        };
        return obj;
      }
      var p3 = new createPerson("Tom3", 12);
      var p4 = new createPerson("Tom4", 12);
      console.log(p3.name, p3.age);

      function createStudent(name, price) {
        var obj = {
          name,
          price,
          setName: function (name) {
            this.name = name;
          },
        };
        return obj;
      }
      var student = new createStudent("张三", 12000);

      /**
       * 4.自定义构造函数模式
       *   套路：通过new创建对象，能解决对象识别问题
       *   适用场景: 需要创建多个类型确定的对象
       *   缺点：每个对象都有相同的数据, 浪费内存
       * */
      function Person(name, age) {
        this.name = name;
        this.age = age;
        this.setName = function (name) {
          this.name = name;
        };
      }
      var person = new Person("Tom4", 12);
      person.setName("Jack4");
      console.log(person.name, person.age);

      /**
       * 5.构造函数+原型模式：最大限度地节省内存
       *   套路：自定义构造函数，属性在函数中初始化，方法添加到原型上
       *   适用场景: 需要创建多个类型确定的对象
       * */
      function Person2(name, age) {
        this.name = name;
        this.age = age;
      }
      //通过原型添加setName()
      Person2.prototype.setName = function (name) {
        this.name = name;
      };

      var person2 = new Person2("Tom5", 12);
      var person3 = new Person2("Jack5", 12);
      console.log(person2, person3);
    </script>
  </body>
</html>
